package com.ocom.payconfig.controller;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.ocom.common.constant.PayConfigUrl;
import com.ocom.common.entity.card.EntityXfDeviceInfo;
import com.ocom.common.entity.master.EntityCompanyPart;
import com.ocom.common.enums.ResultEnum;
import com.ocom.common.request.payconfig.*;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.DateUtils;
import com.ocom.common.utils.ResultUtil;
import com.ocom.common.utils.StaticCodePayUtil;
import com.ocom.common.utils.StringUtils;
import com.ocom.payconfig.service.*;
import com.ocom.payconfig.vo.GetConsDeviceInfoVo;
import com.ocom.redis.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 消费2.14	getConsDeviceInfo
 * 消费2.15	addConsDeviceInfo
 * 消费2.16	updateConsDeviceInfo
 * 消费2.17	deleteConsDeviceInfo
 */
@Slf4j
@RestController
public class ConsDeviceInfoController {

    @Autowired
    XfDeviceInfoService xfDeviceInfoService;

    @Autowired
    ReceiptAddressService receiptAddressService;

    @Autowired
    DishesCommonService dishesCommonService;

    @Autowired
    CompanyPartService companyPartService;

    @Autowired
    XfDeviceMealConfigService xfDeviceMealConfigService;

    @Resource
    private RedisUtil redisUtil;

    // 2.14.获取消费设备信息(getConsDeviceInfo)
    @PostMapping(PayConfigUrl.Url_getConsDeviceInfo)
    public Result getConsDeviceInfo(@RequestBody GetConsDeviceInfoRequest request){
        PageInfo<EntityXfDeviceInfo> pageInfo=xfDeviceInfoService.getConsDeviceInfo(request.getCom_id(),request);
        if(request.isPickOne()){
            if(pageInfo==null || pageInfo.getList().size()<=0){
                return ResultUtil.success();
            }
            return ResultUtil.success(pageInfo.getList().get(0));
        }
        return ResultUtil.success(pageInfo);
    }

    //2.15.添加消费设备信息(addConsDeviceInfo)
    @PostMapping(PayConfigUrl.Url_addConsDeviceInfo)
    public Result addConsDeviceInfo(@RequestBody AddConsDeviceInfoRequest request){
        try {
            EntityXfDeviceInfo entityXfDeviceInfo = xfDeviceInfoService.GetDeviceInfo(request.getComId(), request.getDeviceNo());
            if (request.getDeviceNo().equals(entityXfDeviceInfo.getDeviceNo())){
                log.error("消费设备重复");
                return ResultUtil.error(ResultEnum.Err_3003);
            }
        }catch (Exception exception){
            log.error("获取消费设备信息失败");
            ResultUtil.error(ResultEnum.Err_2009,"获取消费设备信息失败");
        }
        EntityXfDeviceInfo entityXfDeviceInfo=xfDeviceInfoService.addConsDeviceInfo(request.getComId(),request);
        xfDeviceInfoService.UpdateResetMach(request.getComId(),request.getDeviceNo());
        if(entityXfDeviceInfo==null){
            return ResultUtil.error(ResultEnum.Err_2016);
        }
        return ResultUtil.success(entityXfDeviceInfo);
    }


    //2.16.修改消费设备信息(updateConsDeviceInfo)
    @PostMapping(PayConfigUrl.Url_updateConsDeviceInfo)
    public Result updateConsDeviceInfo(@RequestBody UpdateConsDeviceInfoRequest request) throws ParseException {
        EntityXfDeviceInfo entityXfDeviceInfo0 = xfDeviceInfoService.GetDeviceInfo(request.getCom_id(),request.getDevice_no());
        EntityXfDeviceInfo entityXfDeviceInfo=xfDeviceInfoService.updateConsDeviceInfo(request.getCom_id(),request);
        xfDeviceInfoService.UpdateResetMach(request.getCom_id(),request.getDevice_no());
        if(entityXfDeviceInfo==null){
            return ResultUtil.error(ResultEnum.Err_3014);
        }
        try {
            if(request.getPoint_id()!=null && !entityXfDeviceInfo0.getPointId().equals(request.getPoint_id())){
                dishesCommonService.resetMachDishesWhite(request.getCom_id(),request.getPoint_id(),request.getDevice_no());
            }
            redisUtil.del("xf_device_info#comId:"+request.getCom_id()+"#machNo:"+request.getDevice_no()+"#");
            redisUtil.del("xf_device_meal_config#comId:"+request.getCom_id()+"#machNo:"+request.getDevice_no()+"#");
        }catch (Exception e){
            log.info("更新消费点异常 ，【{}】【{}】",request,e);
        }
        return ResultUtil.success(entityXfDeviceInfo);
    }

    //2.17.删除消费设备信息(deleteConsDeviceInfo)
    @PostMapping(PayConfigUrl.Url_deleteConsDeviceInfo)
    public Result deleteConsDeviceInfo(@RequestBody DeleteConsDeviceInfoRequest request){
        boolean b=xfDeviceInfoService.deleteConsDeviceInfo(request.getCom_id(),request);
        if(!b){
            return ResultUtil.error(ResultEnum.Err_3013);
        }else {
            xfDeviceMealConfigService.delConsDeviceMealConfig(request.getCom_id(),request.getDevice_no());

            return ResultUtil.success();
        }

    }

    // 2.14.获取消费设备信息(getConsDeviceList)
    @PostMapping(PayConfigUrl.Url_getConsDeviceList)
    public Result GetConsDeviceList(@Validated @RequestBody GetConsDeviceInfoVo getConsDeviceInfoVo){
        if (getConsDeviceInfoVo.getComId() == null){
            log.error("获取消费设备列表单位编号为空");
            return ResultUtil.error(ResultEnum.Err_203,"获取消费设备列表单位编号为空");
        }
        Map<String, Object> map = new HashMap<>();
        try {
            List<EntityXfDeviceInfo> entityXfDeviceInfos = xfDeviceInfoService.GetConsDeviceList(getConsDeviceInfoVo.getComId(), getConsDeviceInfoVo);
            entityXfDeviceInfos.forEach(item -> {
                item.setCommTime(getCommTime(item.getDeviceNo(),item.getCommTime()));
                item.setFaceErr(getFaceErr(item.getComId(),item.getDeviceNo()));
            });

            PageInfo<EntityXfDeviceInfo> entityXfDeviceInfoPageInfo = new PageInfo<>(entityXfDeviceInfos);
            map.put("total",entityXfDeviceInfoPageInfo.getTotal());
            map.put("list",entityXfDeviceInfos);
        }catch (Exception exception){
            log.error(exception.getMessage());
            log.error("获取消费设备列表执行数据库失败");
            return ResultUtil.error(ResultEnum.Err_2009,"获取消费设备列表执行数据库失败");
        }
        return ResultUtil.success(map);
    }


    private Date getCommTime(String machNo,Date commTime){
        Object obj = redisUtil.get("HttpMachCommTime:"+machNo);
        if(obj!=null){
            return (Date) obj;
        }
        if(commTime==null){
            commTime = DateUtils.strToDate("2020-01-01 12:34:56");
        }
        redisUtil.set("HttpMachCommTime:"+machNo,commTime);
        return commTime;
    }

    //2.52全量下传白名单 (resendWhiteList)
    @PostMapping(PayConfigUrl.Url_ResendWhiteList)
    public Result resendWhiteList(@RequestBody JSONObject jsonObject){
        log.info("全量下传白名单 (resendWhiteList) 【{}】",jsonObject);
        JSONArray jsonArray=jsonObject.getJSONArray("machNo");
        String strMachNo = StringUtils.join(jsonArray, ",");
        boolean b=xfDeviceInfoService.UpdateList(jsonObject.getLong("companyId"),strMachNo);
        if(!b){
            return ResultUtil.error(ResultEnum.Err_3014);
        }else {
            return ResultUtil.success();
        }
    }

    //2.53重置设备参数 (resetMach)
    @PostMapping(PayConfigUrl.Url_ResetMach)
    public Result resetMach(@RequestBody JSONObject jsonObject){
        JSONArray jsonArray=jsonObject.getJSONArray("machNo");
        String strMachNo = StringUtils.join(jsonArray, ",");
        boolean b=xfDeviceInfoService.UpdateResetMach(jsonObject.getLong("companyId"),strMachNo);
        if(!b){
            return ResultUtil.error(ResultEnum.Err_3014);
        }else {
            return ResultUtil.success();
        }
    }


    //2.62获取代理商消费设备信息(getConsDeviceInfoByAgent)
    @PostMapping(PayConfigUrl.Url_getConsDeviceInfoByAgent)
    public Result getConsDeviceInfoByAgent(@RequestBody GetConsDeviceInfoByAgentRequest request){

        Map<String,Object> objectMap =new HashMap<>();
        if(request.getComIds()==null || request.getComIds().size()==0){
            objectMap.put("total",0);
            objectMap.put("list",new ArrayList<>());
            return ResultUtil.success(objectMap);
        }

        List<EntityCompanyPart> list = companyPartService.getDataSourceList();

        List<EntityXfDeviceInfo> agentMachs= new ArrayList<>();

        for (EntityCompanyPart entityCompanyPart:list){
            List<EntityXfDeviceInfo>  machList =xfDeviceInfoService.getMachList(entityCompanyPart.getBeginComId(),request);
            if(machList!=null) agentMachs.addAll(machList);
        }

        //split page
        List<EntityXfDeviceInfo> subList = agentMachs.stream().skip((request.getPage()-1)*request.getSize()).limit(request.getSize()).
                collect(Collectors.toList());


        objectMap.put("total",agentMachs.size());
        objectMap.put("list",subList);
        return ResultUtil.success(objectMap);
    }

    /**
     *@Description:生成设备收款码(getConsDevicePayCode)
     * @author lu 
     * @param companyId
     * @param machNo
     * @return com.ocom.common.resp.Result
     * @date 2023/3/10 10:22       
     */
    @PostMapping(PayConfigUrl.Url_getConsDevicePayCode)
    public Result getConsDevicePayCode(Long companyId,String machNo){
        String code= StaticCodePayUtil.getCode(1,companyId,machNo);
        String codeUrl="http://gzh.ocom30.com/pay?org=" +code;
        Boolean b=xfDeviceInfoService.updateCodeUrl(companyId,machNo,codeUrl);
        if (b){
            Map<String,Object> objectMap =new HashMap<>();
            objectMap.put("codeUrl",codeUrl);
            return ResultUtil.success(objectMap);
        }else {
            return ResultUtil.error(ResultEnum.Err_4074);
        }
    }

    @PostMapping(PayConfigUrl.Url_setMealOrderCode)
    public Result setMealOrderCode(Long companyId,Integer receiptId){
        String code= StaticCodePayUtil.getCode2(3L, companyId, receiptId);
        String codeUrl="http://gzh.ocom30.com/order/foods?org=" +code;

        String code2= StaticCodePayUtil.getCode2(5L, companyId, receiptId);
        String codeUrl2="http://gzh.ocom30.com/shop/plan?org=" +code2;

        Boolean b=receiptAddressService.updateCodeUrl(companyId, receiptId, codeUrl, codeUrl2);
        if (b){
            Map<String,Object> objectMap =new HashMap<>();
            objectMap.put("codeUrl1",codeUrl);
            objectMap.put("codeUrl2",codeUrl2);
            return ResultUtil.success(objectMap);
        }else {
            return ResultUtil.error(ResultEnum.Err_4069);
        }
    }

    /**
     *@Description:删除设备收款码(removeConsDevicePayCode)
     * @author lu 
     * @param companyId
     * @param machNo 
     * @return com.ocom.common.resp.Result
     * @date 2023/3/10 13:17       
     */
    @PostMapping(PayConfigUrl.Url_removeConsDevicePayCode)
    public Result removeConsDevicePayCode(Long companyId,String machNo){
        Boolean b=xfDeviceInfoService.removeConsDevicePayCode(companyId,machNo);
        if (b){
            return ResultUtil.success();
        }else {
            return ResultUtil.error(ResultEnum.Err_3016);
        }
    }

    @PostMapping(PayConfigUrl.Url_getDeviceInfo)
    public Result getDeviceInfo(@RequestParam("comId") Long comId, @RequestParam("machNo")String machNo){
        return ResultUtil.success(xfDeviceInfoService.GetDeviceInfo(comId, machNo));
    }


    @PostMapping(PayConfigUrl.Url_getDeviceInfoMigrate)
    public Result getDeviceInfoMigrate(@RequestParam("comId") Long comId, @RequestParam("machNo")String machNo){
        EntityXfDeviceInfo entityXfDeviceInfo = xfDeviceInfoService.getDeviceInfo2(comId, machNo,2025l);
        if(entityXfDeviceInfo!=null){
            return ResultUtil.error(ResultEnum.Err_6003);
        }
        EntityXfDeviceInfo entityXfDeviceInfo1 = xfDeviceInfoService.getDeviceInfo2(comId, machNo,2026l);
        if(entityXfDeviceInfo1!=null){
            return ResultUtil.success();
        }else{
            return ResultUtil.error(ResultEnum.Err_6002);
        }
    }


    @PostMapping(PayConfigUrl.Url_delSession)
    public Result delSession(@RequestParam("comId") Long comId){
        xfDeviceInfoService.deleteSession(comId);
        return ResultUtil.success();
    }



    /**
     * 生成账户付款码
     * @param companyId
     * @param machNo
     * @return
     */
    @PostMapping(PayConfigUrl.Url_getConsAccountPayCode)
    public Result getConsAccountPayCode(Long companyId,String machNo){
        String code= StaticCodePayUtil.getCode(1,companyId,machNo);
        String codeUrl="http://gzh.ocom30.com/payVirtual?org=" +code;
        Boolean b=xfDeviceInfoService.updateAccountCodePicUrl(companyId,machNo,codeUrl);
        if (b){
            Map<String,Object> objectMap =new HashMap<>();
            objectMap.put("codeUrl",codeUrl);
            return ResultUtil.success(objectMap);
        }else {
            return ResultUtil.error(ResultEnum.Err_4074);
        }
    }


    @PostMapping(PayConfigUrl.Url_removeConsAccountPayCode)
    public Result removeConsAccountPayCode(Long companyId,String machNo){
        Boolean b=xfDeviceInfoService.removeConsAccountPayCode(companyId,machNo);
        if (b){
            return ResultUtil.success();
        }else {
            return ResultUtil.error(ResultEnum.Err_3016);
        }
    }


    private Long getFaceErr(Long comId,String machNo){
        String date = DateUtils.getStrDate(new Date(),"yyyyMMddHH") ;
        String faceErrKey ="FaceErr:" + comId +":" + machNo + ":" + date;
        Long errNum =  redisUtil.hmLen(faceErrKey);

        if(errNum>0l) return errNum;

        // 获取当前时间的毫秒数
        long currentTimeMillis = new Date().getTime();

        // 计算一小时的毫秒数 (1小时 * 60分钟 * 60秒 * 1000毫秒)
        long oneHourInMillis =  60 * 60 * 1000;

        // 减去一小时
        Date oneHourAgo = new Date(currentTimeMillis - oneHourInMillis);
        System.out.println("一小时前: " + oneHourAgo);

        date = DateUtils.getStrDate(oneHourAgo, "yyyyMMddHH");
        faceErrKey = "FaceErr:" + comId + ":" + machNo + ":" + date;

        return redisUtil.hmLen(faceErrKey);

    }



}
